package com.ericsson.enap.modules.topology.service.impl;

import com.csvreader.CsvReader;
import com.ericsson.enap.modules.topology.entity.CabSwitch;
import com.ericsson.enap.modules.topology.entity.EpcCabLinkEdge;
import com.ericsson.enap.modules.topology.entity.EpcCabLinkFromCsv;
import com.ericsson.enap.modules.topology.entity.EpcCabLinkNode;
import com.ericsson.enap.modules.topology.entity.EpcCabSwitchLayout;
import com.ericsson.enap.modules.monitor.mapper.CabSwitchMapper;
import com.ericsson.enap.modules.topology.mapper.EpcCabLinkComboMapper;
import com.ericsson.enap.modules.topology.mapper.EpcCabLinkEdgeMapper;
import com.ericsson.enap.modules.topology.mapper.EpcCabLinkNodeMapper;
import com.ericsson.enap.modules.topology.entity.EpcCabLinkCombo;
import com.ericsson.enap.modules.topology.service.CabTopologySyncService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.FileReader;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Service
public class CabTopologySyncServiceImpl  implements CabTopologySyncService  {

    @Autowired
    private EpcCabLinkComboMapper epcCabLinkComboMapper;
    @Autowired
    private EpcCabLinkEdgeMapper epcCabLinkEdgeMapper;
    @Autowired
    private EpcCabLinkNodeMapper epcCabLinkNodeMapper;
    @Autowired
    private CabSwitchMapper cabSwitchMapper;

    public static final String concatCombo = "|||";
    public static final String splitCombo = "\\|\\|\\|";
    public static final String tenGigabitEthernet = "Ten-GigabitEthernet";
    public static final String fortyGigE = "FortyGigE";
    public static final String pci = "PCI-";
    public static final String gi = "Gi";
    public static final String te = "Te";
    public static final String xgei = "xgei-";
    public static final String xgeis = "xgeis-";
    public static final String _10GE = "10GE";
    public static final String xlgei = "xlgei-";
    public static final String _40GE = "40GE";
    public static final String gigabitEthernet = "GigabitEthernet";
    public static final String comma = ",";
    public static final Integer brLength = 12;

    @Override
    public void syncTopologyData() {
        //解析csv文件
        List<EpcCabLinkCombo> comboList = new ArrayList<>();
        List<EpcCabLinkNode> nodeList = new ArrayList<>();
        List<EpcCabLinkEdge>  edgeList = new ArrayList<>();
        List<EpcCabLinkFromCsv> csvList = readCsvFromDir("E:/CSV");
        //csvList = removeTheSameData(csvList);
        csvList = removeRepeatData(csvList);
        //key:rootName,value,uuid
        Map<String,String> map = new HashMap<>();
        parseCsvToList(csvList,comboList,nodeList,edgeList,map);

        //新增一个步骤,将 comboList 中 pid = 0 的情况录入到 nodeList 表中
        comboList.stream().filter(x->"0".equals(x.getPid())).forEach(x->{
            EpcCabLinkNode linkNode = new EpcCabLinkNode();
            linkNode.setId(map.get(x.getName()));
            linkNode.setComboId("0");
            linkNode.setName(x.getName());
            linkNode.setFullName(x.getFullName());
            linkNode.setRootName(x.getRootName());
            linkNode.setRootId(x.getRootId());
            linkNode.setG6Label(x.getName());
            linkNode.setG6Type(x.getG6Type());
            nodeList.add(linkNode);
        });

        //与数据库进行比较进行增、删、改
        //数据库中的数据
        List<EpcCabLinkCombo> comboListFromDb = epcCabLinkComboMapper.selectLinkComboList();
        List<EpcCabLinkEdge> edgeListFromDb = epcCabLinkEdgeMapper.selectLinkEdgeList();
        List<EpcCabLinkNode> nodeListFromDb = epcCabLinkNodeMapper.selectLinkNodeList();
        //需要添加、删除的comboList
        List<EpcCabLinkCombo> needDeleteComboList = new ArrayList<>();
        List<EpcCabLinkCombo> needAddComboList = new ArrayList<>();
        compareComboList(comboListFromDb,comboList,needDeleteComboList,needAddComboList);
        //需要添加、删除的nodeList
        List<EpcCabLinkNode> needDeleteNodeList = new ArrayList<>();
        List<EpcCabLinkNode> needAddNodeList = new ArrayList<>();
        compareNodeList(nodeListFromDb,comboListFromDb,nodeList,needDeleteNodeList,needAddNodeList);

        //查询数据库进行数据整合成可比较的格式
        parseDbEdge(edgeListFromDb,nodeListFromDb);
        //需要添加、修改(vlan)、删除的edgeList
        List<EpcCabLinkEdge> needDeleteEdgeList = new ArrayList<>();
        List<EpcCabLinkEdge> needAddEdgeList = new ArrayList<>();
        List<EpcCabLinkEdge> needUpdateEdgeList = new ArrayList<>();
        compareEdgeList(edgeListFromDb,comboListFromDb,edgeList,needDeleteEdgeList,needAddEdgeList,needUpdateEdgeList);
        updateDb(needDeleteComboList,needAddComboList,needDeleteNodeList,needAddNodeList,needDeleteEdgeList,needAddEdgeList,needUpdateEdgeList);

        //新增逻辑，对照位置信息表，将linkNode中不存在的节点的信息补充录入到linkNode表中
        this.addAllNode();
    }

    private void addAllNode() {
        //1、查询所有交换机列表
        List<EpcCabLinkCombo> list = epcCabLinkComboMapper.queryLinkComboList();
        List<EpcCabLinkCombo> switchList = list.stream().filter(x->!x.getName().contains("-S")).collect(Collectors.toList());
        int len = switchList.size();
        EpcCabLinkCombo switchCombo;
        //2、遍历交换机列表
        for (int i = 0; i < len; i++) {
            switchCombo = switchList.get(i);
            //2.1、在该交换机下查询linkNode的map集合
            Map<String, EpcCabLinkNode> linkNodeMap = epcCabLinkNodeMapper.queryLinkNodeMap(switchCombo.getRootId());
            //2.2、在该交换机下查询位置信息List集合
            String switchName = switchCombo.getName();
            List<String> layoutList = this.querySwitchLayoutList(switchName);
            if(layoutList.size()>0){
                EpcCabLinkNode node;
                for (int x = 0; x < layoutList.size(); x++) {
                    String[] arr = layoutList.get(x).split(comma);
                    for (int y = 0; y < arr.length; y++) {
                        String key = switchName + concatCombo + arr[y];
                        if(!linkNodeMap.containsKey(key)){
                            node = new EpcCabLinkNode();
                            node.setId(generateUUID());
                            node.setComboId(switchCombo.getId());
                            node.setName(arr[y]);
                            node.setRootName(switchName);
                            setG6LabelByNodeName(arr[y],node,switchName);
                            setNodeType(node);
                            node.setFullName(switchName + concatCombo + arr[y]);
                            node.setRootId(switchCombo.getRootId());
                            epcCabLinkNodeMapper.insertLinkNode(node);
                        }
                    }
                }
            }
        }
    }

    //在该交换机下查询位置信息List集合
    private List<String> querySwitchLayoutList(String switchName) {
        List<String> layoutList = new ArrayList<>();
        //过滤最后的数字，例如：C0105-ToR2，过滤出2
        String num = switchName.replaceAll(".*[^\\d](?=(\\d+))","");
        String name = switchName.substring(0,switchName.lastIndexOf(num));
        CabSwitch epcCabSwitch = cabSwitchMapper.queryEpcCabSwitchLikeByName(name,num);
        if(epcCabSwitch!=null){
            String model = epcCabSwitch.getModel();
            Long irf_flag = epcCabSwitch.getIrfFlag();
            List<EpcCabSwitchLayout> epcCabSwitchLayouts = cabSwitchMapper.querySwitchLayout(model, irf_flag);
            if(epcCabSwitchLayouts.size()>0){
                layoutList = epcCabSwitchLayouts.stream().map(x -> x.getRowValue()).collect(Collectors.toList());
            }
        }
        return layoutList;
    }

    private void updateDb(List<EpcCabLinkCombo> needDeleteComboList,List<EpcCabLinkCombo> needAddComboList,
                          List<EpcCabLinkNode> needDeleteNodeList,List<EpcCabLinkNode> needAddNodeList,
                          List<EpcCabLinkEdge> needDeleteEdgeList,List<EpcCabLinkEdge> needAddEdgeList,List<EpcCabLinkEdge> needUpdateEdgeList) {
        for(EpcCabLinkCombo deleteCombo:needDeleteComboList) {
            epcCabLinkComboMapper.deleteLinkCombo(deleteCombo);
        }
        for(EpcCabLinkCombo addCombo:needAddComboList) {
            epcCabLinkComboMapper.insertLinkCombo(addCombo);
        }
        for(EpcCabLinkNode deleteNode:needDeleteNodeList) {
            epcCabLinkNodeMapper.deleteLinkNode(deleteNode);
        }
        for(EpcCabLinkNode addNode:needAddNodeList) {
            epcCabLinkNodeMapper.insertLinkNode(addNode);
        }
        for(EpcCabLinkEdge deleteEdge:needDeleteEdgeList) {
            epcCabLinkEdgeMapper.deleteLinkEdge(deleteEdge);
        }
        for(EpcCabLinkEdge updateEdge:needUpdateEdgeList) {
            epcCabLinkEdgeMapper.updateLinkEdge(updateEdge);
        }
        for(EpcCabLinkEdge addEdge:needAddEdgeList) {
            epcCabLinkEdgeMapper.insertLinkEdge(addEdge);
        }
    }

    /*
     * 与数据库中的数据进行比较，形成 需要删除的集合，和新增的集合
     * @param comboListFromDb
     * @param comboList
     */
    private void compareComboList(List<EpcCabLinkCombo> comboListFromDb,List<EpcCabLinkCombo> comboList,List<EpcCabLinkCombo> needDeleteComboList,List<EpcCabLinkCombo> needAddComboList) {
        for(EpcCabLinkCombo dbCombo : comboListFromDb) {
            List<EpcCabLinkCombo> combos = comboList.stream().filter(s -> s.getFullName().equalsIgnoreCase(dbCombo.getFullName())).collect(Collectors.toList());
            if(combos.size() <= 0) {
                //数据库当前的记录在新集合中不存在，添加到删除集合中
                needDeleteComboList.add(dbCombo);
            }

        }

        for(EpcCabLinkCombo combo : comboList) {
            List<EpcCabLinkCombo> combos = comboListFromDb.stream().filter(s -> s.getFullName().equalsIgnoreCase(combo.getFullName())).collect(Collectors.toList());
            if(combos.size() <= 0) {
                //新记录在数据库中不存在，添加到新增集合中
                List<EpcCabLinkCombo> rootCombo = comboListFromDb.stream().filter(s -> s.getName().equalsIgnoreCase(combo.getRootName())).collect(Collectors.toList());
                if(rootCombo.size()>0) {
                    combo.setRootId(rootCombo.get(0).getRootId());
                }
                needAddComboList.add(combo);
            }
        }
    }

    private void compareNodeList(List<EpcCabLinkNode> nodeListFromDb,  List<EpcCabLinkCombo> comboListFromDb,List<EpcCabLinkNode> nodeList,List<EpcCabLinkNode> needDeleteNodeList,List<EpcCabLinkNode> needAddNodeList) {
        for(EpcCabLinkNode dbNode : nodeListFromDb) {
            List<EpcCabLinkNode> nodes = nodeList.stream().filter(s -> s.getFullName().equalsIgnoreCase(dbNode.getFullName())).collect(Collectors.toList());
            if(nodes.size() <= 0) {
                needDeleteNodeList.add(dbNode);
            }
        }
        for(EpcCabLinkNode node : nodeList) {
            List<EpcCabLinkNode> nodes = nodeListFromDb.stream().filter(s -> s.getFullName().equalsIgnoreCase(node.getFullName())).collect(Collectors.toList());
            if(nodes.size() <= 0) {
                //如果存在跟节点，则直接引用跟节点id
                List<EpcCabLinkCombo> rootCombo = comboListFromDb.stream().filter(s -> s.getName().equalsIgnoreCase(node.getRootName())).collect(Collectors.toList());
                if(rootCombo.size()>0) {
                    node.setRootId(rootCombo.get(0).getRootId());
                }
                //如果存在父combo则直接引用父类comboid
                List<EpcCabLinkCombo> parentCombo = comboListFromDb.stream().filter(s-> s.getFullName().equalsIgnoreCase(node.getFullName().substring(0,node.getFullName().lastIndexOf(concatCombo)))).collect(Collectors.toList());
                if(parentCombo.size()>0) {
                    node.setComboId(parentCombo.get(0).getId());
                }
                needAddNodeList.add(node);
            }
        }
    }

    private void compareEdgeList(List<EpcCabLinkEdge> edgeListFromDb,List<EpcCabLinkCombo> comboListFromDb,List<EpcCabLinkEdge>  edgeList,List<EpcCabLinkEdge> needDeleteEdgeList,
                                 List<EpcCabLinkEdge> needAddEdgeList,List<EpcCabLinkEdge> needUpdateEdgeList) {
        for(EpcCabLinkEdge dbEdge  : edgeListFromDb) {
            boolean isDelete = true;
            for(EpcCabLinkEdge  edge :  edgeList) {
                if(compareEdge(dbEdge,edge)) {
                    if(!dbEdge.getVlanNum().equals(edge.getVlanNum())) {
                        dbEdge.setVlanNum(edge.getVlanNum());
                        needUpdateEdgeList.add(dbEdge);
                    }
                    isDelete = false;
                    break;
                }
            }
            if(isDelete) {
                needDeleteEdgeList.add(dbEdge);
            }
        }
        for(EpcCabLinkEdge edge  : edgeList) {
            boolean isAdd = true;
            for(EpcCabLinkEdge dbEdge : edgeListFromDb)  {
                if(compareEdge(dbEdge,edge)) {
                    isAdd = false;
                    break;
                }
            }
            if(isAdd) {
                List<EpcCabLinkCombo> comboSourceList = comboListFromDb.stream().filter(s->s.getName().equalsIgnoreCase(edge.getSourceFullName().substring(0,edge.getSourceFullName().indexOf(concatCombo)))).collect(Collectors.toList());
                if(comboSourceList.size()>0) {
                    edge.setSourceRootId(comboSourceList.get(0).getId());
                }

                List<EpcCabLinkCombo> comboTargetList = comboListFromDb.stream().filter(s->s.getName().equalsIgnoreCase(edge.getTargetFullName().substring(0,edge.getTargetFullName().indexOf(concatCombo)))).collect(Collectors.toList());
                if(comboTargetList.size()>0) {
                    edge.setTargetRootId(comboTargetList.get(0).getId());
                }
                needAddEdgeList.add(edge);
            }
        }

    }

    private void parseDbEdge(List<EpcCabLinkEdge> edgeListFromDb,List<EpcCabLinkNode> nodeListFromDb) {
        for(EpcCabLinkEdge edge:edgeListFromDb) {
           /* List<EpcCabLinkNode> sourceNode = nodeListFromDb.stream().filter(s->s.getId().equals(edge.getSourceLinkId())).collect(Collectors.toList());
            List<EpcCabLinkNode> targetNode = nodeListFromDb.stream().filter(s->s.getId().equals(edge.getTargetLinkId())).collect(Collectors.toList());*/
            List<EpcCabLinkNode> sourceNode = nodeListFromDb.stream().filter(s->s.getFullName().equals(edge.getSourceFullName())).collect(Collectors.toList());
            List<EpcCabLinkNode> targetNode = nodeListFromDb.stream().filter(s->s.getFullName().equals(edge.getTargetFullName())).collect(Collectors.toList());
            if(sourceNode.size() > 0) {
                EpcCabLinkNode node = sourceNode.get(0);
                edge.setSourceCombo(node.getFullName().substring(0,node.getFullName().lastIndexOf(concatCombo)));
                edge.setSourceNode(node.getFullName().substring(node.getFullName().lastIndexOf(concatCombo)+3));
                edge.setSourceRootId(node.getRootId());
                edge.setSourceFullName(node.getFullName());
            }
            if(targetNode.size() > 0) {
                EpcCabLinkNode node = targetNode.get(0);
                edge.setTargetCombo(node.getFullName().substring(0,node.getFullName().lastIndexOf(concatCombo)));
                edge.setTargetNode(node.getFullName().substring(node.getFullName().lastIndexOf(concatCombo)+3));
                edge.setTargetRootId(node.getRootId());
                edge.setTargetFullName(node.getFullName());
            }
        }

    }

    //通过原始csv集合生成combo集合
    private void parseCsvToList(List<EpcCabLinkFromCsv> csvList, List<EpcCabLinkCombo> comboList, List<EpcCabLinkNode> nodeList,
                                List<EpcCabLinkEdge>  edgeList, Map<String,String> map) {

        for(EpcCabLinkFromCsv csv : csvList) {
            //实例化combo
            EpcCabLinkCombo lastSourceCombo = putComboList(csv.getSourceCombo(),comboList);
            EpcCabLinkCombo lastTargetCombo = putComboList(csv.getTargetCombo(),comboList);
            //实例化node
            EpcCabLinkNode sourceNode = putNodeList(csv.getSourceCombo(),csv.getSourceNode(),lastSourceCombo,nodeList);
            EpcCabLinkNode targetNode = putNodeList(csv.getTargetCombo(),csv.getTargetNode(),lastTargetCombo,nodeList);
            //实例化edge
            //如果本端 对端的combo 和 node相同则 去掉自链接的连线，保存该节点
            if(!sourceNode.getFullName().equalsIgnoreCase(targetNode.getFullName())) {
                putEdgeList(sourceNode,targetNode,csv,edgeList,map);
            }
        }
    }

    private void putEdgeList(EpcCabLinkNode sourceNode, EpcCabLinkNode targetNode, EpcCabLinkFromCsv cvs, List<EpcCabLinkEdge>  edgeList, Map<String,String> map) {
        EpcCabLinkEdge edge = new EpcCabLinkEdge();
        edge.setSourceLinkId(sourceNode.getId());
        edge.setTargetLinkId(targetNode.getId());
        edge.setSourceCombo(cvs.getSourceCombo());
        edge.setSourceNode(cvs.getSourceNode());
        edge.setTargetCombo(cvs.getTargetCombo());
        edge.setTargetNode(cvs.getTargetNode());

        if(!map.containsKey(cvs.getSourceCombo())){
            map.put(cvs.getSourceCombo(),generateUUID());
        }
        if(!map.containsKey(cvs.getTargetCombo())){
            map.put(cvs.getTargetCombo(),generateUUID());
        }

        edge.setVlanNum(cvs.getVlan());
        edge.setSourceRootId(sourceNode.getRootId());
        edge.setSourceFullName(sourceNode.getFullName());
        edge.setTargetRootId(targetNode.getRootId());
        edge.setTargetFullName(targetNode.getFullName());
        setEdgeG6Type(sourceNode, targetNode, edge);
        if(sourceNode.getRootId().equals(targetNode.getRootId())){
            edge.setLogicType(0);
            edge.setId(generateUUID());
            edgeList.add(edge);
        }else{
            //节点对节点的线
            EpcCabLinkEdge edge1 = new EpcCabLinkEdge();
            BeanUtils.copyProperties(edge,edge1);
            edge1.setLogicType(1);
            edge1.setId(generateUUID());
            edgeList.add(edge1);

            //combo(父)对combo(父)的线（会重复，后面去重只留一条线）
           /* boolean b = edgeList.stream().filter(x->
                    (x.getSourceLinkId().equals(sourceNode.getRootId()) && x.getTargetLinkId().equals(targetNode.getRootId())))
                    .findAny().isPresent();*/
            boolean b = true;
            for (int i = 0; i < edgeList.size(); i++) {
                if(edgeList.get(i).getSourceLinkId().equals(map.get(sourceNode.getRootName())) && edgeList.get(i).getTargetLinkId().equals(map.get(targetNode.getRootName()))){
                    b = false;
                }
            }
            if(b){
                EpcCabLinkEdge edge2 = new EpcCabLinkEdge();
                BeanUtils.copyProperties(edge,edge2);
                edge2.setLogicType(2);
                edge2.setSourceLinkId(map.get(sourceNode.getRootName()));
                edge2.setSourceFullName(sourceNode.getRootName());
                edge2.setTargetLinkId(map.get(targetNode.getRootName()));
                edge2.setTargetFullName(targetNode.getRootName());
                edge2.setId(generateUUID());
                edgeList.add(edge2);
            }

            //combo(父)对节点的线
            EpcCabLinkEdge edge3_1 = new EpcCabLinkEdge();
            BeanUtils.copyProperties(edge,edge3_1);
            edge3_1.setLogicType(3);
            edge3_1.setSourceLinkId(map.get(sourceNode.getRootName()));
            edge3_1.setSourceFullName(sourceNode.getRootName());
            edge3_1.setId(generateUUID());
            edgeList.add(edge3_1);

            //节点对combo(父)的线
            EpcCabLinkEdge edge3_2 = new EpcCabLinkEdge();
            BeanUtils.copyProperties(edge,edge3_2);
            edge3_2.setLogicType(3);
            edge3_2.setTargetLinkId(map.get(targetNode.getRootName()));
            edge3_2.setTargetFullName(targetNode.getRootName());
            edge3_2.setId(generateUUID());
            edgeList.add(edge3_2);
        }
    }

    private void setEdgeG6Type(EpcCabLinkNode sourceNode, EpcCabLinkNode targetNode, EpcCabLinkEdge edge) {
        boolean sourceNodeIsEq100 = sourceNode.getG6Type()!=null?sourceNode.getG6Type()==100:false;
        boolean targetNodeIsEq100 = targetNode.getG6Type()!=null?targetNode.getG6Type()==100:false;
        boolean sourceNodeIsEq110 = sourceNode.getG6Type()!=null?sourceNode.getG6Type()==110:false;
        boolean targetNodeIsEq110 = targetNode.getG6Type()!=null?targetNode.getG6Type()==110:false;
        boolean sourceNodeIsEq140 = sourceNode.getG6Type()!=null?sourceNode.getG6Type()==140:false;
        boolean targetNodeIsEq140 = targetNode.getG6Type()!=null?targetNode.getG6Type()==140:false;
        if(sourceNodeIsEq100||targetNodeIsEq100){
            edge.setG6Type(100);
        }
        if(sourceNodeIsEq110||targetNodeIsEq110){
            edge.setG6Type(110);
        }
        if(sourceNodeIsEq140||targetNodeIsEq140){
            edge.setG6Type(140);
        }
    }

    /*
     * @param combos,nodeName   当前数据全名 A.b.c n1 - A.b.c.n1
     * @param combo  当前记录上一个combo对象
     * @param nodeList  符合条件的数据存储在 nodeList中
     * @return EpcCabLinkNode 返回新加的节点，如果没添加则返回上一个查询到的节点
     */
    private EpcCabLinkNode putNodeList(String combos,String nodeName,EpcCabLinkCombo combo,List<EpcCabLinkNode> nodeList) {
        String nodeFullName = combos + concatCombo + nodeName;
        List<EpcCabLinkNode> searchNode = nodeList.stream().filter(s -> s.getFullName().equalsIgnoreCase(nodeFullName)).collect(Collectors.toList());
        if(searchNode.size() <= 0) {
            //当前节点不存在，添加记录到nodeList中
            EpcCabLinkNode currNode = new EpcCabLinkNode();
            currNode.setId(generateUUID());
            currNode.setComboId(combo.getId());
            currNode.setName(nodeName);
            setG6LabelByNodeName(nodeName, currNode,combo.getRootName());
            if(currNode.getG6Label().length()>brLength){
                currNode.setG6Label(setBr(currNode.getG6Label()));
            }
            currNode.setFullName(nodeFullName);
            currNode.setRootName(combo.getRootName());
            currNode.setRootId(combo.getRootId());
            setNodeType(currNode);
            nodeList.add(currNode);
            return currNode;
        }
        return searchNode.get(0);
    }

    //给太长的字符串加入换行符号的小算法
    private String setBr(String str){
        int strLen = str.length();
        int n = strLen/brLength;
        List<String> list = new ArrayList<>();
        String needStr = "";
        String leftStr = str;
        for (int i = 0; i < n; i++) {
            needStr = leftStr.substring(0,brLength);
            leftStr = leftStr.substring(brLength,leftStr.length());
            list.add(needStr);
        }
        if(!(strLen%brLength==0)){
            needStr = leftStr.substring(0,leftStr.length());
            list.add(needStr);
        }
        StringBuffer newStr = new StringBuffer();
        for (int i = 0; i < list.size(); i++) {
            newStr.append(list.get(i));
            if(i!=list.size()-1){
                newStr.append("\n");
            }
        }
        System.out.println(newStr.toString());
        return newStr.toString();
    }

    private void setG6LabelByNodeName(String nodeName, EpcCabLinkNode currNode,String rootName) {
        boolean b = !rootName.contains("-S");
        if(nodeName.contains(tenGigabitEthernet) && b){
            currNode.setG6Label(nodeName.substring(tenGigabitEthernet.length()));
        }else if(nodeName.contains(fortyGigE) && b){
            currNode.setG6Label(nodeName.substring(fortyGigE.length()));
        }else if(nodeName.contains(pci) && b){
            currNode.setG6Label(nodeName.substring(pci.length()));
        }else if(nodeName.contains(gigabitEthernet) && b){
            currNode.setG6Label(nodeName.substring(gigabitEthernet.length()));
        }else if(nodeName.contains(te) && b){
            currNode.setG6Label(nodeName.substring(te.length()));
        }else if(nodeName.contains(xgeis) && b){
            currNode.setG6Label(nodeName.substring(xgeis.length()));
        }else if(nodeName.contains(xgei) && b){
            currNode.setG6Label(nodeName.substring(xgei.length()));
        }else if(nodeName.contains(xlgei) && b){
            currNode.setG6Label(nodeName.substring(xlgei.length()));
        }else if(nodeName.contains(_10GE) && b){
            currNode.setG6Label(nodeName.substring(_10GE.length()));
        }else if(nodeName.contains(_40GE) && b){
            currNode.setG6Label(nodeName.substring(_40GE.length()));
        }else if(nodeName.contains(gi) && b){
            currNode.setG6Label(nodeName.substring(gi.length()));
        }else{
            currNode.setG6Label(nodeName);
        }
    }

    private void setNodeType(EpcCabLinkNode currNode) {
        String nodeName = currNode.getName();
        String pattern100_0 = "^Gi\\d+/\\d+";
        String pattern100_1 = "^GigabitEthernet\\d+/\\d+";
        String pattern100_2 = "^GigabitEthernet\\d+/\\d+/\\d+";
        boolean type100_0 = nodeNameMatcher(pattern100_0,nodeName);
        boolean type100_1 = nodeNameMatcher(pattern100_1,nodeName);
        boolean type100_2 = nodeNameMatcher(pattern100_2,nodeName);
        if("IPMI".equalsIgnoreCase(nodeName) || "NICX".equalsIgnoreCase(nodeName) || type100_0 || type100_1 || type100_2) {
            currNode.setG6Type(100);
            return;
        }
        String pattern140_0 = "^FortyGigE\\d+/\\d+/\\d+/\\d+";
        String pattern140_3 = "^FortyGigE\\d+/\\d+/\\d+";
        String pattern140_1 = "^xlgei-\\d+/\\d+/\\d+/\\d+";
        String pattern140_2 = "^40GE\\d+/\\d+/\\d+";
        boolean type140_0 = nodeNameMatcher(pattern140_0,nodeName);
        boolean type140_3 = nodeNameMatcher(pattern140_3,nodeName);
        boolean type140_1 = nodeNameMatcher(pattern140_1,nodeName);
        boolean type140_2 = nodeNameMatcher(pattern140_2,nodeName);
        if(type140_0 || type140_1 || type140_2 || type140_3) {
            currNode.setG6Type(140);
            return;
        }
        String pattern110_0 = "^Te\\d+/\\d+";
        boolean type110_0 = nodeNameMatcher(pattern110_0,nodeName);
        String pattern110_1 = "^Ten-GigabitEthernet\\d+/\\d+/\\d+";
        boolean type110_1 = nodeNameMatcher(pattern110_1,nodeName);
        String pattern110_2 = "^PCI-.+-.+";
        boolean type110_2 = nodeNameMatcher(pattern110_2,nodeName);
        String pattern110_3 = "^xgei-\\d+/\\d+/\\d+/\\d+";
        boolean type110_3 = nodeNameMatcher(pattern110_3,nodeName);
        String pattern110_4 = "^xgeis-\\d+/\\d+/\\d+/\\d+";
        boolean type110_4 = nodeNameMatcher(pattern110_4,nodeName);
        String pattern110_5 = "^10GE/\\d+/\\d+/\\d+";
        String pattern110_5_1 = "^10GE\\d+/\\d+/\\d+";
        boolean type110_5 = nodeNameMatcher(pattern110_5,nodeName);
        boolean type110_5_1 = nodeNameMatcher(pattern110_5_1,nodeName);
        String pattern110_6 = "^NICX-PORT.";
        boolean type110_6 = nodeNameMatcher(pattern110_6,nodeName);
        String pattern110_7 = "[1-3][0-9]|[1-9]|[4][0-8]";
        boolean type110_7 = nodeNameMatcher(pattern110_7,nodeName);
        if(type110_0 || type110_1 || type110_2 || type110_3 || type110_4 || type110_5 || type110_5_1 || type110_6 || type110_7) {
            currNode.setG6Type(110);
            return;
        }
    }

    private boolean nodeNameMatcher(String pattern,String nodeName) {
        Pattern p = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
        boolean result = p.matcher(nodeName).matches();
        return result;
    }

    /**
     *
     * @param combo
     * @param comboList
     * @return  返回combo关联的最后一个节点
     */
    private EpcCabLinkCombo putComboList(String combo, List<EpcCabLinkCombo> comboList) {
        String[] combos = combo.split(splitCombo);
        String currCombo = "";
        String rootName = "";
        String rootId = "";
        EpcCabLinkCombo preNode = null;
        for(int i=0; i<combos.length; i++) {
            currCombo += combos[i];
            String finalCurrCombo = currCombo;
            List<EpcCabLinkCombo> searchCombo = comboList.stream().filter(s -> s.getFullName().equalsIgnoreCase(finalCurrCombo)).collect(Collectors.toList());
            if(searchCombo.size()<=0) {
                //添加新combo到comboList
                String id = generateUUID();  //需要关联edge表
                EpcCabLinkCombo com = new EpcCabLinkCombo();
                com.setId(id);
                if(i==0) {
                    //跟节点
                    com.setPid("0");
                    rootName = combos[i];
                    if(rootName.contains("-S")) {
                        com.setG6Type(201);
                    } else {
                        com.setG6Type(202);
                    }
                    rootId = id;

                } else {
                    //子节点
                    if(preNode != null) {
                        com.setPid(preNode.getId());
                        rootName=preNode.getRootName();
                        rootId=preNode.getRootId();
                    }
                }
                com.setName(combos[i]);
                com.setFullName(currCombo);
                com.setG6Level(currCombo.split(splitCombo).length-1);
                com.setRootName(rootName);
                com.setRootId(rootId);
                comboList.add(com);
                preNode = com;
            } else {
                preNode=searchCombo.get(0);
            }
            if(i < combos.length-1) {
                currCombo += concatCombo;
            }
        }
        return preNode;
    }

    /**
     * 读取指定目录下csv文件并组装成list
     * @param dir
     * @return
     */
    private List<EpcCabLinkFromCsv> readCsvFromDir(String dir) {
        CsvReader reader = null;
        File[] files = new File(dir).listFiles();
        List<EpcCabLinkFromCsv> csvList = new ArrayList<>();
        for(File file : files) {
            try {
                reader = new CsvReader(new FileReader(file.getAbsolutePath()));
                while (reader.readRecord()) {
                    EpcCabLinkFromCsv csv = new EpcCabLinkFromCsv();
                    String sourceCombo = reader.get(0);
                    String sourceNode = reader.get(1);
                    String targetCombo = reader.get(2);
                    String targetNode = reader.get(3);
                    String vlan = "".equals(reader.get(5))?"999999":reader.get(5);
                    csv.setSourceCombo(sourceCombo);
                    csv.setSourceNode(sourceNode);
                    csv.setTargetCombo(targetCombo);
                    csv.setTargetNode(targetNode);
                    csv.setVlan(vlan);
                    csv.setVlanList(conversArray(vlan));
                    csvList.add(csv);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if(null != reader) reader.close();
            }
        }
        return csvList;
    }

    /**
     * 去除重复的csv记录，并合并vlan取交集
     * 例：视为同一条记录
     * a.b.c www  -  d.e.f  zzz
     * d.e.f  zzz - a.b.c www
     *
     * @return
     */
    private List<EpcCabLinkFromCsv> removeRepeatData(List<EpcCabLinkFromCsv> csvList) {
        List<EpcCabLinkFromCsv> result = new ArrayList<>();
        for(int i=0; i<csvList.size(); i++) {
            EpcCabLinkFromCsv currCsv= csvList.get(i);
            if(!existCsv(result,currCsv))  {  //判断当前记录是否在返回列表已经存在
                boolean repeat = false;
                //与当前记录相同的的记录
                List<EpcCabLinkFromCsv> repeatList = new ArrayList<>();
                for(int j=i+1; j<csvList.size(); j++) {
                    EpcCabLinkFromCsv compareCsv = csvList.get(j);
                    if(compareCsv(currCsv,compareCsv)) {
                        repeatList.add(compareCsv);
                        repeat = true;
                    }
                }
                if(repeat) {
                    repeatList.add(currCsv);
                    //vlan 取交集
                    List<Integer> intersectionList = new ArrayList<>();
                    for(int j=0; j<repeatList.size(); j++) {
                        List<Integer> subvlan = repeatList.get(j).getVlanList();
                        if(j==0) {
                            intersectionList = subvlan;
                        } else {
                            intersectionList = intersectionList.stream().filter(item -> subvlan.contains(item)).collect(Collectors.toList());
                        }
                    }
                    currCsv.setVlan(StringUtils.join(intersectionList,","));
                } else {
                    currCsv.setVlan(StringUtils.join(currCsv.getVlanList(),","));
                }
                result.add(currCsv);
            }
        }
        return result;
    }

    /*
     *
     * vlan 转成list集合
     * @param vlan
     * @return
     */
    private List<Integer> conversArray(String vlan) {
        List<Integer> result = new ArrayList<>();
        if(!StringUtils.isEmpty(vlan)) {
            String[] vlanList = vlan.split(";");
            for(String lan : vlanList) {
                if(lan.contains("-")) {
                    String[] range = lan.split("-");
                    for(int i=Integer.parseInt(range[0]); i<=Integer.parseInt(range[1]); i++) {
                        result.add(i);
                    }
                } else {
                    result.add(Integer.parseInt(lan));
                }
            }
        }
        return result;
    }

    private boolean existCsv(List<EpcCabLinkFromCsv> result,EpcCabLinkFromCsv currCsv) {
        for(EpcCabLinkFromCsv csv : result) {
            if(compareCsv(csv,currCsv)) {
                return true;
            }
        }
        return false;
    }

    private boolean compareCsv(EpcCabLinkFromCsv csv1, EpcCabLinkFromCsv csv2) {
        return compare(csv1.getSourceCombo(), csv2.getSourceCombo(), csv1.getSourceNode(),
                csv2.getSourceNode(), csv1.getTargetCombo(), csv2.getTargetCombo(), csv1.getTargetNode(), csv2.getTargetNode());
    }

    private boolean compareEdge(EpcCabLinkEdge csv1, EpcCabLinkEdge csv2) {

        return compare(csv1.getSourceCombo(), csv2.getSourceCombo(), csv1.getSourceNode(), csv2.getSourceNode(), csv1.getTargetCombo(),
                csv2.getTargetCombo(), csv1.getTargetNode(), csv2.getTargetNode());
    }

    private boolean compare(String sourceCombo, String sourceCombo2, String sourceNode, String sourceNode2,
                            String targetCombo, String targetCombo2, String targetNode, String targetNode2) {
        if((sourceCombo.equalsIgnoreCase(sourceCombo2)
                && sourceNode.equalsIgnoreCase(sourceNode2)
                && targetCombo.equalsIgnoreCase(targetCombo2)
                && targetNode.equalsIgnoreCase(targetNode2))
                || (sourceCombo.equalsIgnoreCase(targetCombo2)
                && sourceNode.equalsIgnoreCase(targetNode2)
                && targetCombo.equalsIgnoreCase(sourceCombo2)
                && targetNode.equalsIgnoreCase(sourceNode2))) {
            return true;
        }
        return false;
    }

    /*
     * 移除combo node 左右都相等的数据
     */
    private List<EpcCabLinkFromCsv> removeTheSameData(List<EpcCabLinkFromCsv> csvList) {
        List<EpcCabLinkFromCsv> newCvsList = new ArrayList<>();
        for(EpcCabLinkFromCsv csv : csvList) {
            if(!(csv.getSourceCombo().equalsIgnoreCase(csv.getTargetCombo()) && csv.getSourceNode().equalsIgnoreCase(csv.getTargetNode()))) {
                newCvsList.add(csv);
            }
        }
        return newCvsList;
    }

    private String generateUUID() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }


}
